from django.utils.encoding import smart_text
from rest_framework.authentication import get_authorization_header
from rest_framework_jwt.settings import api_settings
from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication
from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import ugettext as _
from .exceptions import JsonAPIException
from . import ErrCode


class AdmJSONWebTokenAuthentication(BaseJSONWebTokenAuthentication):
    """
    Clients should authenticate by passing the token key in the "Authorization"
    HTTP header, prepended with the string specified in the setting
    `JWT_AUTH_HEADER_PREFIX`. For example:

        Authorization: JWT eyJhbGciOiAiSFMyNTYiLCAidHlwIj
    """
    www_authenticate_realm = 'api'

    def get_user_id_from_payload(self, payload):
        try:
            user_id = payload['uid']
        except KeyError:
            msg = _('missing claim uid')
            raise JsonAPIException(code=ErrCode.AUTH_FAILED.name, msg=msg, status=401)
        return user_id

    def authenticate_credentials(self, payload):
        """
        Returns an active user that matches the payload's user id and email.
        """
        from django.contrib.auth.models import User as DjangoUser
        user_id = self.get_user_id_from_payload(payload)
        print(user_id)
        try:
            user = DjangoUser.objects.get(id=user_id)
        except ObjectDoesNotExist:
            msg = _('User Does Not Exists')
            raise JsonAPIException(code=ErrCode.AUTH_FAILED.name, msg=msg, status=401)
        except ValueError:
            msg = '身份认证失败'
            raise JsonAPIException(code=ErrCode.AUTH_FAILED.name, msg=msg, status=401)

        if not( user.is_staff and user.is_active):
            msg = _('User account is disabled.')
            raise JsonAPIException(code=ErrCode.AUTH_FAILED.name, msg=msg, status=401)

        return user

    def get_jwt_value(self, request):
        auth = get_authorization_header(request).split()
        auth_header_prefix = api_settings.JWT_AUTH_HEADER_PREFIX.lower()

        if not auth:
            if api_settings.JWT_AUTH_COOKIE:
                return request.COOKIES.get(api_settings.JWT_AUTH_COOKIE)
            return None

        if smart_text(auth[0].lower()) != auth_header_prefix:
            return None

        if len(auth) == 1:
            msg = _('验证信息不能为空')
            raise JsonAPIException(code=ErrCode.AUTH_FAILED.name, msg=msg, status=401)
        elif len(auth) > 2:
            msg = _('验证信息格式不正确')
            raise JsonAPIException(code=ErrCode.AUTH_FAILED.name, msg=msg, status=401)

        return auth[1]

    def authenticate_header(self, request):
        """
        Return a string to be used as the value of the `WWW-Authenticate`
        header in a `401 Unauthenticated` response, or `None` if the
        authentication scheme should return `403 Permission Denied` responses.
        """
        return '{0} realm="{1}"'.format(api_settings.JWT_AUTH_HEADER_PREFIX, self.www_authenticate_realm)

